import java.util.Random;
import java.util.Arrays;
import java.lang.Math;

public class Test2
{
    public static void main(String[] args)
    {
        Test2 t = new Test2();
        t.run();
    }

    public void run()
    {
        int n = 1000;
        int repeats = 100;
        Random r = new Random();

        // initialize random data drawn from normal distribution N(0, 1)                                          
        double[] data = new double[n];
        for (int i = 0; i < n; i++)
            data[i] = r.nextGaussian();

        // created sorted version of the data                                                                     
	double[] dataSorted = new double[n];
        for (int i = 0; i < n; i++)
            dataSorted[i] = data[i];
        Arrays.sort(dataSorted);

        // compute the real KS statistic
        double KposReal = 0.0, KnegReal = 0.0;
	for (double mu = -1.0; mu <= 1.0; mu += 1.0)
	    for (double sigma = -1.0; sigma <= 1.0; sigma += 1.0)
	    {
		KposReal = 0.0; KnegReal = 0.0;
		for (int i = 0; i < n; i++)
		    {
			KposReal = Math.max(KposReal, (i + 1.0)/n - cdfNormal(dataSorted[i], mu, sigma));
			KnegReal = Math.max(KnegReal, cdfNormal(dataSorted[i], 0, 1) - ((double)i)/n);
		    }
		System.out.println("mu = " + mu + ", sigma = " + sigma + "\nKpos = " + KposReal + "\nKneg = " + KnegReal + "\n");
	    }
    }

    // the cdf of N(mu, sigma) on value x
    public static double cdfNormal(double x, double mu, double sigma)
    {
        return 0.5 + 0.5 * erf((x - mu)/(sigma * Math.sqrt(2.0)));
    }

    // erf function taken from:                                                                                   
    // http://introcs.cs.princeton.edu/java/21function/ErrorFunction.java.html                                    
    // fractional error in math formula less than 1.2 * 10 ^ -7.                                                  
    // although subject to catastrophic cancellation when z in very close to 0                                    
    // from Chebyshev fitting formula for erf(z) from Numerical Recipes, 6.2                                      
    public static double erf(double z) {
        double t = 1.0 / (1.0 + 0.5 * Math.abs(z));
        // use Horner's method                                                                                    
        double ans = 1 - t * Math.exp( -z*z   -   1.26551223 +
                                       t * ( 1.00002368 +
                                             t * ( 0.37409196 +
                                                   t * ( 0.09678418 +
                                                         t * (-0.18628806 +
                                                              t * ( 0.27886807 +
                                                                    t * (-1.13520398 +
                                                                         t * ( 1.48851587 +
                                                                               t * (-0.82215223 +
                                                                                    t * ( 0.17087277))))))))));
        if (z >= 0) return  ans;
        else        return -ans;
    }

    


}